package com.temp.aspect;

import com.temp.annotation.AutoFill;
import com.temp.constant.AutoFillConstant;
import com.temp.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 自定义切面类，实现公共字段自动填充处理逻辑
 */
@Aspect
@Slf4j
@Component
public class AutoFillAspect {

    /**
     * 切入点
     */
    @Pointcut("execution(* com.temp.mapper.*.*(..)) && @annotation(com.temp.annotation.AutoFill)")
    public void autoFillPointCut() {
    }

    /**
     * 前置通知，在通知中进行公共字段的赋值
     */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint) {
        log.info("开始进行公共字段的自动填充...");

        // 获取到当前被拦截的方法上的数据库操作类型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();// 方法签名对象
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);// 获得方法上的注解对象
        OperationType value = autoFill.value();// 获得数据库操作类型
        // 获取到当前被拦截的方法的参数--实体对象
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return;
        }

        HashMap<Object, Method[]> methodHashMap = new HashMap<>();
        // 存放所有方法和参数对象
        for (Object arg : args) {
            Class<?> aClass = arg.getClass();
            Method[] methods = aClass.getDeclaredMethods();
            methodHashMap.put(arg, methods);
        }
        // 判断是更新操作还是添加操作
        for (Map.Entry<Object, Method[]> entry : methodHashMap.entrySet()) {
            Object key = entry.getKey();
            for (Method method : entry.getValue()) {
                String name = method.getName();
                try {
                    if (name.equals(AutoFillConstant.SET_UPDATE_TIME) || (name.equals(AutoFillConstant.SET_CREATE_TIME))) {
                        method.invoke(key, LocalDateTime.now());
                    }
                } catch (InvocationTargetException | IllegalAccessException e) {
                    throw new IllegalArgumentException("自动填充操作类型参数异常！");
                }
            }
        }
    }
}